local modeDynamic = 0
local modeStatic = 1
local mode = 0
local length = 256
local position = 0
local boosterSpacing = 32
local fuelSlot = 1
local materialSlot = 2
local torchSlot = 3
local poweredRailSlot = 4
local railSlot = 5
local currentRailSlot = railSlot
local lastBooster = boosterSpacing - 2
local turtleElevated = true
local placeMaterialAroundTorches = true
local placeMaterialUnderRail = true
local removeObstacles = false
local returnTurtle = false
local outOfMaterial = "Ran out of material"
local refillMaterial = "Refill material and press enter"
local outOfTorches = "Ran out of redstone torches"
local refillTorches = "Refill redstone torches and press enter"
local outOfPoweredRails = "Ran out of powered rails"
local refillPoweredRails = "Refill powered rails and press enter"
local outOfRails = "Ran out of rails"
local refillRails = "Refill rails and press enter"
local railPlacementFailed = "Failed to place rails, check turtle"
local poweredRailPlacementFailed = "Failed to place powered rails, check turtle"
local torchPlacementFailed = "Failed to place redstone torch, check turtle"
local materialPlacementFailed = "Failed to place material, check turtle"
local pressEnterToContinue = "Press enter to continue"
local refuelingTurtle = "Low fuel detected, refueling"
local outOfFuel = "Turtle out of fuel, waiting for refuel"
local railwayCompleted = "Rail laying completed"
local turtleReturning = "Turtle returning to start"
local turtleReturned = "Turtle returned to start position"
local obstacleEncountered = "Obstacle encountered, waiting"
local author = "Kevin Scroggins"
local nickname = "nitro glycerine"
local email = "nitro404@gmail.com
local website = "http://www.nitro404.com"

function checkFuel()
  if turtle.getItemCount(fuelSlot) == 0 then
    print(outOfFuel)
    
    while turtle.getItemCount(fuelSlot) == 0 do
      os.sleep(1)
    end
  end
  
  if turtle.getFuelLevel() < 15 then
    print(refuelingTurtle)
    turtle.select(fuelSlot)
    if turtle.refuel(1) ~= true then
      print(outOfFuel)
      
      while turtle.refuel(1) ~= true do
        os.sleep(1)
      end
    end
    
    checkFuel()
  end
end

function forward(d)
  if d == nil then
    d = 1
  elseif d < 1 then
    return
  end
  
  for i = 0, d - 1, 1 do
    checkFuel()
    
    if turtle.forward() ~= true then
      print(obstacleEncountered)
      
      while turtle.forward() ~= true do
        checkFuel()
        
        if removeObstacles == true then
          turtle.dig()
        end
        
        os.sleep(0.5)
      end
    end
  end
  
  checkFuel()
end

function back(d)
  if d == nil then
    d = 1
  elseif d < 1 then
    return
  end
  
  for i = 0, d - 1, 1 do
    checkFuel()
    
    if turtle.back() ~= true then
      print(obstacleEncountered)
      
      while turtle.back() ~= true do
        checkFuel()
        
        os.sleep(0.5)
      end
    end
  end
  
  checkFuel()
end

function up(d)
  if d == nil then
    d = 1
  elseif d < 1 then
    return
  end
  
  for i = 0, d - 1, 1 do
    checkFuel()
    
    if turtle.up() ~= true then
      print(obstacleEncountered)
      
      while turtle.up() ~= true do
        checkFuel()
        
        if removeObstacles == true then
          turtle.digUp()
        end
        
        os.sleep(0.5)
      end
    end
  end
  
  checkFuel()
end

function down(d)
  if d == nil then
    d = 1
  elseif d < 1 then
    return
  end
  
  for i = 0, d - 1, 1 do
    checkFuel()
    
    if turtle.down() ~= true then
      print(obstacleEncountered)
      
      while turtle.down() ~= true do
        checkFuel()
        
        if removeObstacles == true then
          turtle.digDown()
        end
        os.sleep(0.5)
      end
    end
  end
  
  checkFuel()
end

function left(n)
  if n == nil then
    n = 1
  elseif n < 1 then
    return
  end
  
  for i = 0, n - 1, 1 do
    turtle.turnLeft()
  end
end

function right(n)
  if n == nil then
    n = 1
  elseif n < 1 then
    return
  end
  
  for i = 0, n - 1, 1 do
    turtle.turnRight()
  end
end

function checkMaterial()
  while turtle.getItemCount(materialSlot) == 0 do
    print(outOfMaterial)
    print(refillMaterial)
    
    io.read()
  end
end

function checkTorches()
  while turtle.getItemCount(torchSlot) == 0 do
    print(outOfTorches)
    print(refillTorches)
    
    io.read()
  end
end

function checkPoweredRails()
  while turtle.getItemCount(poweredRailSlot) == 0 do
    print(outOfPoweredRails)
    print(refillPoweredRails)
    
    io.read()
  end
end

function checkRails()
  while turtle.getItemCount(currentRailSlot) == 0 do
    if currentRailSlot == 16 then
      currentRailSlot = railSlot
      
      print(outOfRails)
      print(refillRails)
      
      io.read()
    else
      currentRailSlot = currentRailSlot + 1
    end
  end
end

function checkAll()
  checkMaterial()
  checkTorches()
  checkPoweredRails()
  checkRails()
  checkFuel()
end

function returnToStart()
  turtle.turnRight()
  turtle.turnRight()
  
  while position > 1 do
    forward()
    
    position = position - 1
  end
  
  return true
end

function placeRail()
  checkRails()
  
  turtle.select(currentRailSlot)
  
  if turtle.placeDown() ~= true then
    if placeMaterialUnderRail == true then
	  down()
      placeMaterialDown()
	  up()
    end
    
    checkRails()
  
    turtle.select(currentRailSlot)
  
    while turtle.placeDown() ~= true do
      print(railPlacementFailed)
	  print(pressEnterToContinue)
      
      io.read()
    
      checkRails()
    end
  end
  
  checkRails()
end

function placePoweredRail()
  checkPoweredRails()
    
  turtle.select(poweredRailSlot)
  
  if turtle.placeDown() ~= true then
    if placeMaterialUnderRail == true then
      placeMaterialDown()
    end
    
    checkPoweredRails()
    
    turtle.select(poweredRailSlot)
    
    while turtle.placeDown() ~= true do
      print(poweredRailPlacementFailed)
	  print(pressEnterToContinue)
      
      io.read()
    
      checkPoweredRails()
    end
  end
  
  checkPoweredRails()
end

function placeTorch()
  if placeMaterialAroundTorches == true then
    placeMaterialAroundTorch()
  end
  
  checkTorches()
    
  turtle.select(torchSlot)
  
  while turtle.placeDown() ~= true do
    print(torchPlacementFailed)
	print(pressEnterToContinue)
    
    io.read()
    
    checkTorches()
  end
  
  checkTorches()
end

function placeMaterialDown()
  checkMaterial()
    
  turtle.select(materialSlot)
  
  while turtle.placeDown() ~= true do
    print(materialPlacementFailed)
	print(pressEnterToContinue)
    
    io.read()
    
    checkMaterial()
  end
  
  checkMaterial()
end

function placeMaterialForward()
  checkMaterial()
    
  turtle.select(materialSlot)
  
  turtle.place()
  
  checkMaterial()
end

function placeMaterialAroundTorch()
  if placeMaterialAroundTorches == true then
    down()
  
    turtle.select(materialSlot)
    
	checkMaterial()
    turtle.placeDown()
    
    placeMaterialForward()
    turtle.turnRight()
    
    placeMaterialForward()
    turtle.turnRight()
    
    placeMaterialForward()
    turtle.turnRight()
    
    placeMaterialForward()
    turtle.turnRight()
    
    up()
  end
end

function checkAndPlaceRail()
  if lastBooster == boosterSpacing - 2 then
    placePoweredRail()
    
    lastBooster = lastBooster + 1
  elseif lastBooster == boosterSpacing - 1 then
    down()
    turtle.digDown()
    down()
    turtle.digDown()
    
    placeTorch()
    
    up()
    
    placeMaterialDown()
    
    up()
    
    placePoweredRail()
    
    lastBooster = 0
  elseif lastBooster == 0 then
    placePoweredRail()
    
    lastBooster = lastBooster + 1
  else
    placeRail()
    
    lastBooster = lastBooster + 1
  end
end

function placeRailsStatic()
  if turtleElevated == true then
    up()
  end
  
  forward()
  
  while position <= length do
    checkAndPlaceRail()
    
    position = position + 1
  end
end

function placeRailsDynamic()
  if turtleElevated == true then
    up()
  end
  
  forward()
  
  checkFuel()
  while true do
    checkAndPlaceRail()
    
    position = position + 1
    
    checkFuel()
    
    if turtle.forward() ~= true then
      break
    end
  end
  
  return position
end

function placeRailway()
  write("Placing railway ")
  if mode == modeStatic then
    write(length)
    write(" long\n")
  elseif mode == modeDynamic then
    write("with dynamic length\n")
  end
  
  checkAll()
  
  if mode == modeStatic then
    placeRailsStatic()
  elseif mode == modeDynamic then
    length = placeRailsDynamic()
  end
  
  print(railwayCompleted)
  write("Railway length: ")
  write(length)
  write("\n")
  
  if returnTurtle == true then
    print(turtleReturning)
    if returnToStart() == true then
      turtle.turnRight()
      turtle.turnRight()
      back()
      
      if turtleElevated == true then
        down()
      end
      
      print(turtleReturned)
    end
  end
end

placeRailway()
